package log

import (
	"os"
	"sync"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// zlog 是一个包装的结构体，封装了 zap 日志和一次性初始化的逻辑
type zlog struct {
	logger *zap.SugaredLogger
	once   sync.Once
	stdout *logFile
}

var (
	log     zlog
	logConf struct {
		Dir     string
		SvrName string
	}
)

// InitLog 初始化日志的存储目录和服务名称
func InitLog(dir, svrName string) {
	if logConf.Dir != "" || logConf.SvrName != "" {
		Panic("log.InitLog(dir,svrName) used twice, not allowd")
	}
	logConf.Dir = dir
	logConf.SvrName = svrName
}

// instance 返回单例的 zap.SugaredLogger 实例
func instance() *zap.SugaredLogger {
	log.once.Do(func() {
		if logConf.Dir == "" || logConf.SvrName == "" {
			panic("log.InitLog(dir,svrName) not used")
		}
		log.stdout = NewLogFile(logConf.Dir, logConf.SvrName)
		encoderConfig := zap.NewProductionEncoderConfig()
		encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000")
		encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder

		fileOutput := zapcore.AddSync(log.stdout)

		core := zapcore.NewCore(
			zapcore.NewConsoleEncoder(encoderConfig),
			zapcore.NewMultiWriteSyncer(fileOutput, os.Stdout),
			zapcore.DebugLevel,
		)

		log.logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)).Sugar()
	})
	return log.logger
}

// 日志记录接口（支持不带格式化和带格式化的日志输出）
func Debug(args ...interface{}) {
	instance().Debug(args...)
}
func Info(args ...interface{}) {
	instance().Info(args...)
}
func Warn(args ...interface{}) {
	instance().Warn(args...)
}
func Error(args ...interface{}) {
	instance().Error(args...)
}
func Fatal(args ...interface{}) {
	instance().Fatal(args...)
}
func Panic(args ...interface{}) {
	instance().Panic(args...)
}
func Debugf(format string, args ...interface{}) {
	instance().Debugf(format, args...)
}
func Infof(format string, args ...interface{}) {
	instance().Infof(format, args...)
}
func Warnf(format string, args ...interface{}) {
	instance().Warnf(format, args...)
}
func Errorf(format string, args ...interface{}) {
	instance().Errorf(format, args...)
}
func Fatalf(format string, args ...interface{}) {
	instance().Fatalf(format, args...)
}
func Panicf(format string, args ...interface{}) {
	instance().Panicf(format, args...)
}
